package generation;

import java.util.ArrayList;
import java.util.Random;

import models.Measure;
import models.Phrase;
import models.Score;
import models.Track;

import org.jfugue.Rhythm;
import org.jfugue.Pattern;

public class Generator {
	
	//divide by the powers of two to get note lengths
	//Octave values 1-10 (1 = Lowest Octave, 10 = Highest Octave)
	//12 semi-tones - Octave * semitone = Numeric values for notes at the begining of octaves.
	//Default Time signature is 4/4 time
	Random random = new Random();
	final int SEMI_TONE_COUNT = 12;
	
	private int octave;
	
	public int[] powersOfTwo = new int[]{2, 4, 8, 16};
	public int[] harmonicValues = new int[]{3, 5, 8};
	public int[] naturalNoteValues = new int[]{0, 2, 4, 5, 7, 9, 11};
	ArrayList<Integer> values = new ArrayList<Integer>();
	ArrayList<Double> lengths = new ArrayList<Double>();
	
	private StringBuilder generatedString;
	
	public Pattern generateNewTrack(Track newTrackModel)
	{
		generatedString = new StringBuilder();
		values = new ArrayList<Integer>();
		lengths = new ArrayList<Double>();
		generatedString.append("T" + newTrackModel.tempo + " " + newTrackModel.keySignature + " ");
		
		Score score = new Score();
		
		for(int i=0; i < newTrackModel.instruments.length; i++)
		{
			if(newTrackModel.instruments[i].equals("Drums"))
			{
				if(i==0)
				{
					generatedString = new StringBuilder();
					generatedString.append("T" + newTrackModel.tempo + " ");
				}
				generateRhythm(newTrackModel);
			}
			else
			{
				generatedString.append("V" + i + " I[" + newTrackModel.instruments[i] + "] ");
				
				score = generateScore(newTrackModel, i, lengths, values);
			}
			getMusicString(score);
		}
		return new Pattern(generatedString.toString());
	}
	
	private Score generateScore(Track newTrackModel, int instrument, ArrayList<Double> prevLength, ArrayList<Integer> prevValue)
	{
		Score score = new Score();
		for(int j=0; j < newTrackModel.phraseAmount; j++)
		{
			Phrase phrase = new Phrase();
			
			octave = random.nextInt(4) + 3;
			Measure measure = new Measure();
			measure.generateMeasures(newTrackModel, instrument, octave, prevLength, prevValue);
			phrase.addMeasure(measure);
			score.addPhrase(phrase);
		}
		return score;
	}
	
	private void getMusicString(Score score) 
	{
		for(Phrase p : score.phrases)
		{
			for(Measure m : p.measures)
			{
				generatedString.append(m.content);
			}
		}
	}

	private void generateRhythm(Track newTrackModel) {
		
		for(int j=0; j < newTrackModel.phraseAmount; j++)
		{
			octave = random.nextInt(4) + 3;
			for(int k=0; k < newTrackModel.measuresPerPhrase; k++)
			{
				Rhythm rhythm = new Rhythm();
				rhythm.setLayer(1, "O..oO...O..oOO..");
				rhythm.setLayer(2, "..*...*...*...*.");
				rhythm.setLayer(3, "^.^.^.^.^.^.^.^.");
				rhythm.setLayer(4, "...............!");
				// Step 2. Identify instruments to use in the beat
				// (In this example, each MusicString should have a
				// total duration of an eighth note)
				rhythm.addSubstitution('O', "[BASS_DRUM]i");
				rhythm.addSubstitution('o', "Rs [BASS_DRUM]s");
				rhythm.addSubstitution('*', "[ACOUSTIC_SNARE]i");
				rhythm.addSubstitution('^',"[PEDAL_HI_HAT]t Rt [CLOSED_HI_HAT]t Rt");
				rhythm.addSubstitution('.', "Ri");
				generatedString.append(rhythm.getPattern().toString());	
			}
		}
	}

	public void generateFromTrack(Track existingTrackModel){
		
	}
	
	public void analyzeTracks(Track firstTrack, Track secondTrack){
		
	}
}
